package com.edu.internship.util;

import com.edu.internship.glabal.constants.Constants;
import com.edu.internship.glabal.constants.ResultCodeEnum;
import com.edu.internship.glabal.exception.BusinessException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

/**
 * code is far away from bug with the animal protecting
 *
 * @author lsq28657638@gmail.com
 * @description 文件操作工具类
 * @date Create in 2018/01/09 16:05
 */
public class StreamUtils {

    private StreamUtils() {
    }

    /**
     * 将InputStream转换成UTF-8的String
     *
     * @param in 输入流
     * @return 字符串
     */
    public static String inputStreamToString(InputStream in) {
        return inputStreamToString(in, StandardCharsets.UTF_8.name());
    }

    /**
     * 将InputStream转换成某种字符编码的String
     *
     * @param in       输入流
     * @param encoding 字符编码
     * @return 字符串
     */
    public static String inputStreamToString(InputStream in, String encoding) {
        try {
            return new String(inputStreamToByte(in), encoding);
        } catch (IOException e) {
            return StringUtils.EMPTY;
        }
    }

    /**
     * 将String转换成UTF-8的InputStream
     *
     * @param in 输入串
     * @return 输入流
     */
    public static InputStream stringToInputStream(String in) {
        return stringToInputStream(in, StandardCharsets.UTF_8.name());
    }

    /**
     * String转换成InputString
     *
     * @param in       输入串
     * @param encoding 字符编码
     * @return 输入流
     */
    public static InputStream stringToInputStream(String in, String encoding) {
        try (ByteArrayInputStream bais = new ByteArrayInputStream(in.getBytes(encoding))) {
            return bais;
        } catch (IOException e) {
            throw new BusinessException(ResultCodeEnum.IO_STREAM_ERROR, e.getMessage());
        }
    }

    /**
     * 从文件中读取流
     *
     * @param file 文件
     * @return byte数组
     */
    public static byte[] getFileBytes(File file) {
        try (FileInputStream fis = StreamUtils.getFileInputStream(file);
             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            IOUtils.copy(fis, baos, Integer.parseInt(Constants.BaseCons.BUFFER_SIZE.getCode()));
            return baos.toByteArray();
        } catch (IOException e) {
            throw new BusinessException(ResultCodeEnum.IO_STREAM_ERROR, e.getMessage());
        }
    }

    /**
     * String转换为字节数组
     *
     * @param str 字符串
     * @return 返回字节数, 组当报错或null的时候返回长度为0的字节数组
     */
    public static byte[] getBytes(String str) {
        if (StringUtils.isBlank(str)) {
            return new byte[]{};
        }
        try {
            return str.getBytes(StandardCharsets.UTF_8.name());
        } catch (IOException e) {
            return new byte[]{};
        }
    }

    /**
     * 将String转换成InputStream
     *
     * @param in 输入串
     * @return 字节码
     */
    public static byte[] stringToByte(String in) {
        return inputStreamToByte(stringToInputStream(in));
    }

    /**
     * 将InputStream转换成byte数组
     *
     * @param in 输入流
     * @return 字节码
     */
    public static byte[] inputStreamToByte(InputStream in) {
        try (ByteArrayOutputStream outStream = new ByteArrayOutputStream()) {
            byte[] data = new byte[Integer.parseInt(Constants.BaseCons.BUFFER_SIZE.getCode())];
            int count;
            while ((count = in.read(data, 0, Integer.parseInt(Constants.BaseCons.BUFFER_SIZE.getCode()))) != -1) {
                outStream.write(data, 0, count);
            }
            outStream.flush();
            return outStream.toByteArray();
        } catch (IOException e) {
            throw new BusinessException(ResultCodeEnum.IO_STREAM_ERROR, e.getMessage());
        }
    }

    /**
     * 将byte数组转换成InputStream
     *
     * @param in 字节码
     * @return 输入流
     */
    public static InputStream byteToInputStream(byte[] in) {
        return new ByteArrayInputStream(in);
    }

    /**
     * 将byte数组转换成String
     *
     * @param in 字节码
     * @return 字符串
     */
    public static String byteToString(byte[] in) {
        return inputStreamToString(byteToInputStream(in));
    }

    /**
     * 根据文件路径创建文件输入流处理 以字节为单位（非 unicode ）
     *
     * @param filePath 文件路径
     * @return 文件输入流
     */
    public static FileInputStream getFileInputStream(String filePath) {
        return getFileInputStream(new File(filePath));
    }

    /**
     * 根据文件对象创建文件输入流处理 以字节为单位（非 unicode ）
     *
     * @param file 文件
     * @return 文件输入流
     */
    public static FileInputStream getFileInputStream(File file) {
        try {
            return new FileInputStream(file);
        } catch (IOException e) {
            throw new BusinessException(ResultCodeEnum.IO_STREAM_ERROR, e.getMessage());
        }
    }

    /**
     * 根据文件路径创建文件输出流处理 以字节为单位（非 unicode ）
     *
     * @param filePath 文件路径
     * @return 文件输出流
     */
    public static FileOutputStream getFileOutputStream(String filePath) {
        return getFileOutputStream(new File(filePath));
    }

    /**
     * 根据文件路径创建文件输出流处理 以字节为单位（非 unicode ）
     *
     * @param file 文件
     * @return 文件输出流
     */
    public static FileOutputStream getFileOutputStream(File file) {
        return getFileOutputStream(file, false);
    }

    /**
     * 根据文件路径创建文件输出流处理 以字节为单位（非 unicode ）
     *
     * @param filePath 文件路径
     * @param append   true:文件以追加方式打开,false:则覆盖原文件的内容
     * @return 文件输出流
     */
    public static FileOutputStream getFileOutputStream(String filePath, boolean append) {
        return getFileOutputStream(new File(filePath), append);
    }

    /**
     * 根据文件对象创建文件输出流处理 以字节为单位（非 unicode ）
     *
     * @param file   文件
     * @param append true:文件以追加方式打开,false:则覆盖原文件的内容
     * @return 文件输出流
     */
    public static FileOutputStream getFileOutputStream(File file, boolean append) {
        try {
            return new FileOutputStream(file, append);
        } catch (IOException e) {
            throw new BusinessException(ResultCodeEnum.IO_STREAM_ERROR, e.getMessage());
        }
    }

}
